package org.linlinjava.litemall.admin.controller.user;

import java.math.BigDecimal;
import java.util.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.linlinjava.litemall.admin.beans.Constants;
import org.linlinjava.litemall.admin.beans.annotation.LogAnno;
import org.linlinjava.litemall.admin.beans.dto.PointsDto;
import org.linlinjava.litemall.admin.beans.dto.UserDto;
import org.linlinjava.litemall.admin.beans.vo.AdminAddressVo;
import org.linlinjava.litemall.admin.controller.user.vo.AdminUserPageReqVO;
import org.linlinjava.litemall.admin.service.AdminAddressService;
import org.linlinjava.litemall.admin.service.AdminUserInfoService;
import org.linlinjava.litemall.admin.service.UserService;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * 管理用户控制器
 *
 * @author yliyun
 * @date 2022/09/14
 */
@Api(tags = "用户操作API")
@RestController
@RequestMapping("/admin/user")
@Validated
public class AdminUserController {

    /**
     * litemall用户服务
     */
    @Autowired
    private LitemallUserService litemallUserService;

    @Autowired
    private LitemallAddressService addressService;
    /**
     * 用户服务
     */
    @Resource
    private UserService userService;
    /**
     * litemall优惠券服务
     */
    @Autowired
    private LitemallCouponService litemallCouponService;
    /**
     * 管理用户信息服务
     */
    @Autowired
    private AdminUserInfoService adminUserInfoService;
    /**
     * litemall充电服务
     */
    @Autowired
    private LitemallRechargeConsumptionService litemallRechargeService;

    @Autowired
    private LitemallOrderService litemallOrderService;

    @Autowired
    private LitemallRegionService regionService;

    @ApiOperation("会员-「删除会员｜物理删除」")
    @ApiImplicitParam(name = "userId",value = "用户ID")
    @GetMapping("/userRemove")
    @LogAnno
    public Object userRemove(@RequestParam("userId")Integer userId){
        return litemallUserService.userRemove(userId)?ResponseUtil.ok():ResponseUtil.fail();
    }


    @ApiOperation("用户分页")
    @GetMapping("/list")
    @LogAnno
    public Object page(AdminUserPageReqVO pageReqVO) {
        List<Integer> userRegionIdList = new ArrayList<>();
        if(pageReqVO.getRegionIds()!=null&&pageReqVO.getRegionIds().size()>0){
            List<Integer> regionIds = pageReqVO.getRegionIds();
            LitemallRegion region = regionService.getById(CollUtil.getLast(regionIds));
            LambdaQueryWrapper<LitemallAddress> lambdaQueryWrapper = new LambdaQueryWrapper();
            Optional.ofNullable(region).ifPresent(r -> {
                if (Constants.ADMINISTRATION_REGION_PROVINCE.equals(r.getType())) {
                    lambdaQueryWrapper.eq(LitemallAddress::getProvince, r.getNameEn());
                } else if (Constants.ADMINISTRATION_REGION_CITY.equals(r.getType())) {
                    lambdaQueryWrapper.eq(LitemallAddress::getCity, r.getNameEn());
                } else {
                    lambdaQueryWrapper.eq(LitemallAddress::getCountry, r.getNameEn());
                }
            });
            List<LitemallAddress> addressList = addressService.list(lambdaQueryWrapper);
            if(addressList.size()==0){
                return ResponseUtil.okPage(new Page<>());
            }
            userRegionIdList = CollectionUtils.convertList(addressList,LitemallAddress::getUserId);
        }

        List<Integer> userConsumeIdList = new ArrayList<>();
        if(pageReqVO.getConsumeTimeRange()!=null&&pageReqVO.getConsumeTimeRange().length>0){
            LambdaQueryWrapper<LitemallOrder> orderWrapper = new LambdaQueryWrapper<>();
            Optional.ofNullable(pageReqVO.getConsumeTimeRange())
                    .filter(range -> range.length == 2 && range[0] != null && range[1] != null)
                    .ifPresent(range -> {
                        orderWrapper.between(LitemallOrder::getAddTime, range[0], range[1]);
                    });
            List<LitemallOrder> litemallOrders = litemallOrderService.list(orderWrapper);
            if(litemallOrders.size()==0){
                return ResponseUtil.okPage(new Page<>());
            }
            userConsumeIdList = CollectionUtils.convertList(litemallOrders,LitemallOrder::getUserId);
        }


        LambdaQueryWrapper<LitemallUser> queryWrapper = new LambdaQueryWrapper<>();
        Optional.ofNullable(userRegionIdList)
            .filter(list -> !list.isEmpty())
            .ifPresent(list -> queryWrapper.in(LitemallUser::getId, list));
        Optional.ofNullable(userConsumeIdList)
                .filter(list -> !list.isEmpty())
                .ifPresent(list -> queryWrapper.in(LitemallUser::getId, list));
        Optional.ofNullable(pageReqVO.getUsername()).ifPresent(username -> queryWrapper.like(LitemallUser::getUsername, username));
        Optional.ofNullable(pageReqVO.getUserLevel()).ifPresent(level -> queryWrapper.eq(LitemallUser::getUserLevel, level));
        Optional.ofNullable(pageReqVO.getStatus()).ifPresent(status -> queryWrapper.eq(LitemallUser::getStatus, status));
        Optional.ofNullable(pageReqVO.getLastLoginTimeRange())
                .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                .ifPresent(range -> queryWrapper.between(LitemallUser::getLastLoginTime, range[0], range[1]));

        Page<LitemallUser> userPage = litemallUserService.page(new Page<>(pageReqVO.getPage(), pageReqVO.getLimit()), queryWrapper);
        return ResponseUtil.okPage(userPage);
    }

    /**
     * 查询用户统计
     * 新增数量统计
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return {@link Object}
     */
    @GetMapping("/queryUserStatistics")
    @LogAnno
    public Object queryUserStatistics( @RequestParam(value = "registerType",required = false) Integer registerType,String startTime, String endTime) {
        return ResponseUtil.ok(userService.queryUserStatistics(registerType,startTime, endTime));
    }

    /**
     * 查询添加用户统计
     * 会员增长统计
     *
     * @param type      类型
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return {@link Object}
     */
    @GetMapping("/queryAddUserStatistics")
    @LogAnno
    public Object queryAddUserStatistics(
                                         @RequestParam(value = "registerType",required = false) Integer registerType,
                                         @NotNull @RequestParam(value = "startTime") String startTime,
                                         @NotNull @RequestParam(value = "endTime") String endTime) {
        return ResponseUtil.ok(userService.queryAddUserStatistics(startTime, endTime,registerType));
    }

    @ApiOperation("按关键字查询")
    @GetMapping("/option")
    @LogAnno
    public Object queryByKeyword(String keyword) {
        return ResponseUtil.ok(userService.queryByKeywordNoInner(keyword));
    }

    /**
     * 余额积分明细
     *
     * @param userId   用户id
     * @param mobile   移动
     * @param username 用户名
     * @param page     页面
     * @param limit    限制
     * @param sort     排序
     * @param order    订单
     * @return {@link Object}
     */
    @GetMapping("/rechargeConsumptionList")
    @LogAnno
    public Object rechargeConsumptionList(
            Integer userId,String mobile, String username,
                   @RequestParam(defaultValue = "1") Integer page,
                   @RequestParam(defaultValue = "10") Integer limit,
                   @Sort @RequestParam(defaultValue = "add_time") String sort,
                   @Order @RequestParam(defaultValue = "desc") String order) {

        List<LitemallRechargeConsumption> litemallRechargeConsumptions = litemallRechargeService.querySelectiveList(userId, username, mobile, page, limit, sort, order);

        for (LitemallRechargeConsumption litemallRechargeConsumption : litemallRechargeConsumptions) {
            LitemallOrder litemallOrder = litemallOrderService.findById(litemallRechargeConsumption.getOrderId());
            if(ObjectUtil.isNotEmpty(litemallOrder)){
                litemallRechargeConsumption.setOrderSn(litemallOrder.getOrderSn());
                litemallRechargeConsumption.setPayType(litemallOrder.getPayType().intValue());
                litemallRechargeConsumption.setMessage(litemallOrder.getMessage());
            }
        }
        return ResponseUtil.okList(litemallRechargeConsumptions);
    }

    /**
     * 查询用户优惠券计数
     * 用户优惠券数量
     *
     * @param userId 用户id
     * @return {@link Object}
     */
    @GetMapping("/queryUserCoupon")
    @LogAnno
    public Object queryUserCouponCount(@NotNull Integer userId) {
        return ResponseUtil.ok(litemallCouponService.queryUserCouponCount(userId));
    }

    /**
     * 用户信息
     *
     * @param userId 用户id
     * @return {@link Object}
     */
    @GetMapping("/info")
    @LogAnno
    public Object userInfo(@NotNull Integer userId) {
        return adminUserInfoService.userInfo(userId);
    }

    /**
     * 账号明细统计
     *
     * @param userId 用户id
     * @return {@link Object}
     */
    @GetMapping("/statistics")
    @LogAnno
    public Object billStatistics(@NotNull Integer userId){
        Map<String, Object> map = new HashMap<>();
        List<LitemallRechargeConsumption> litemallRechargeConsumptions = litemallRechargeService.queryByUserId(userId);
        BigDecimal totalSaving = new BigDecimal(0.0);
        BigDecimal totalConsume = new BigDecimal(0.0);
        BigDecimal totalBalance = new BigDecimal(0.0);
        BigDecimal totalRefund = new BigDecimal(0.0);
        for(LitemallRechargeConsumption item : litemallRechargeConsumptions){
            if(item.getType().equals(Constants.USER_SAVING)){
                totalSaving = totalSaving.add(item.getAmount());
            }else if(!item.getType().equals(Constants.USER_SAVING)&&!item.getType().equals(Constants.LOG_GIFTCARD_REFUND)){
                totalConsume = totalConsume.add(item.getAmount());
            }else if(item.getType().equals(Constants.LOG_GIFTCARD_REFUND)){
                totalRefund=totalRefund.add(item.getAmount());
            }
        }
        LitemallUser user = litemallUserService.findById(userId);
        totalBalance = totalBalance.add(user.getAvailableAmount());
        map.put("totalSaving",totalSaving);
        map.put("totalConsume",totalConsume);
        map.put("totalBalance",totalBalance);
        map.put("totalRefund",totalRefund);
        return ResponseUtil.ok(map);
    }

    /**
     * resetpwd
     * 重置密码
     *
     * @param userId 用户id
     * @param newPwd 新pwd
     * @return {@link Object}
     */
    @PutMapping("/resetpwd")
    @LogAnno
    public Object resetpwd(@NotNull Integer userId, String newPwd) {
        return adminUserInfoService.resetPwd(userId, newPwd);
    }


    /**
     * 积分
     * 赠送积分
     *
     * @param userId   用户id
     * @param integral 积分
     * @return {@link Object}
     */
    @PutMapping("/integral")
    @LogAnno
    public Object integral(@NotNull Integer userId, Integer integral) {
        return adminUserInfoService.integral(userId, integral);
    }

    /**
     * 更新
     * 修改用户信息
     *
     * @param dto dto
     * @return {@link Object}
     */
    @PutMapping("/update")
    @LogAnno
    public Object update(@Valid @RequestBody UserDto dto) {
        return adminUserInfoService.update(dto);
    }

    /**
     * 更新积分
     *
     * @param dto dto
     * @return {@link Object}
     */
    @PutMapping("/updatePoint")
    @LogAnno
    public Object updatePoint(@Valid @RequestBody PointsDto dto) {
        return adminUserInfoService.updatePoint(dto);
    }

    /**
     * 用户信息页面添加积分明细条目
     *
     * @param userId 用户id
     * @param type   类型
     * @param page   页面
     * @param limit  限制
     * @param sort   排序
     * @param order  订单
     * @return {@link Object}
     */
    @GetMapping("/pointDetail")
    @LogAnno
    public Object pointDetail(@NotNull Integer userId,Byte type,@RequestParam(defaultValue = "1") Integer page,
                              @RequestParam(defaultValue = "10") Integer limit,
                              @RequestParam(defaultValue = "add_time") String sort,
                              @RequestParam(defaultValue = "desc") String order) {
        return adminUserInfoService.pointDetail(userId,page,limit,sort,order,type);
    }

    /**
     * 格兰特exten优惠券
     *
     * @param userId         用户id
     * @param selectCouponId 选择优惠券id
     * @param num            全国矿工工会
     * @param remark         备注
     * @return {@link Object}
     */
    @PostMapping("/grantExtenCoupon")
    @LogAnno
    public Object grantExtenCoupon(@NotNull Integer userId,@NotNull Integer selectCouponId,@NotNull Integer num,String remark) {
//        return adminUserInfoService.pointDetail(userId,page,limit,sort,order,type);
        return adminUserInfoService.grantExtenCoupon(userId,selectCouponId,num,remark);
    }

    @ApiOperation("用户信息-「clvoer明细」")
    @GetMapping("/cloverDetail")
    @LogAnno
    public Object cloverDetail(@NotNull Integer userId,Integer page,Integer limit){
        return adminUserInfoService.cloverDetail(userId,page,limit);
    }




}
